package com.bb.blog.code.threading;


import java.util.Scanner;
import java.util.concurrent.Semaphore;

/**
 * 记录Semaphore的获取流程
 *
 * =========================== acquire() ===============================================
 * 1. acquire()
 * 2. acquireSharedInterruptibly()
 *   2.1. tryAcquireShared()
 *      2.1.1 公平锁
 *          ①等待队列里第一个节点指向的线程是不是自己
 *          ②是自己就直接获取锁 ------- 但是不知道是怎么从节点中删除的
 *          ③不是就返回-1
 *      2.1.2 非公平锁
 *   通过2.1的返回值判断是否能直接获取到锁没有获取到锁执行2.2
 *   2.2. doAcquireSharedInterruptibly
 *      2.2.1 如果队列没有初始化就初始化队列需要有一个空的节点并将head和tail都指向空节点
 *      2.2.2 将当前节点添加都尾部
 *      2.2.3 再去重复 2.1 如果获取到锁了 进行传播-----
 *      2.2.4 如果没有获取到就进行 unpark()
 *
 *
 *==============================   release () =================================
 * 1. tryReleaseShared() 主要任务是将state进行加减
 * 2. doReleaseShared() 主要任务是unpack阻塞的节点
 *   2.0 判断是否有 阻塞的线程
 *   2.1 获取当前 head 从 SIGNAL 转到 0 状态 否则一直循环
 *   2.2 将当前 head 从 0 设置为 -3（） 否则一直循环
 *   ----- 有多少次release 就有多少个线程进入循环 且在acquire启动之前都不会退出
 *   2.3 当head没有变化后  退出循环
 *
 */
public class SemaphoreSample {

    public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(0,true);
        for (int i = 0; i < 1; i++) {
            new Thread(new Task(semaphore, "krosus" + i)).start();
//            Scanner scanner = new Scanner(System.in);
//            StringBuilder help = new StringBuilder();
//            help.append("请输入" + "：");
//            System.out.println(help.toString());
//            scanner.next();
//            semaphore.release(3);
            continue;
        }
//        Thread.sleep(300);
//        semaphore.release();

    }

    static class Task extends Thread {
        Semaphore semaphore;

        public Task(Semaphore semaphore, String tname) {
            this.semaphore = semaphore;
            this.setName(tname);
        }

        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + ": acquire() at time :" + System.currentTimeMillis());
                semaphore.acquire();

//                semaphore.release();
                System.out.println(Thread.currentThread().getName() + ": release() at time:" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
